#ifndef GNLOG_H
#define GNLOG_H
#include "GnCriticalSection.h"
#include <log4cplus/logger.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <GnCustomiseLog4cplus.h>
#include <vector>

typedef log4cplus::Appender* (* AppendFileFunc) (eAppenderType appendType,
	const log4cplus::tstring& logerName, const log4cplus::tstring& filename,
	long maxFileSize, int maxBackupIndex, bool immediateFlush);

typedef log4cplus::Appender* (* AppenOutputDebugFunc) (eAppenderType appendType,
	const log4cplus::tstring& logerName);

typedef void (* WriteLogFunc) (const log4cplus::tstring logerName,
	log4cplus::tstring message, int logLevel);

typedef void (* WriteFromLoggerLogFunc) (log4cplus::Logger* logger,
	log4cplus::tstring message, int logLevel);


class GNSYSTEM_ENTRY GnLogger
{
	GnStaticDeclareFlags(guchar);
public:
	enum
	{
		USE_FILELOG_MASK = 0X0001,
		USE_OUTPUTDEBUG_MASK = 0X0002,
	};
	
public:
	static GnLogger* GetInstance();

	static void EBMStartup();
	static void EBMShutdown();
	void Init();

	static bool UseUserSystemLog(bool useLog = true);
	inline void SetUseLogger(gtchar* name);
	
	inline void SetOutputDebug(const gtchar* logerName);
	inline void SetOutputFile(const gtchar* logerName, const gtchar* filename, long maxFileSize = 10*1024*1024,
		int maxBackupIndex = 1, bool immediateFlush = true);
	
	GNFORCEINLINE void WriteLog(const gtchar* format, ...);
	GNFORCEINLINE void WriteError(const gtchar* format, ...);
	GNFORCEINLINE void WriteWarring(const gtchar* format, ...);
	GNFORCEINLINE void WriteAlways(const gtchar* logName, const gtchar* format, ...);	
	void WriteOutputDebug(gtchar* format, ...);

	GNFORCEINLINE static void SetUseFileLog(bool useLog);
	GNFORCEINLINE static bool GetUseFileLog();
	GNFORCEINLINE static void SetUseOutputDebug(bool useLog);
	GNFORCEINLINE static bool GetUseOutputDebug();
protected:
	void Write(const gtchar* logName, int logLevel, const gtchar* format, va_list& kArgs);
	GNFORCEINLINE void LineCheck( gtchar* message, gsize& messageLength );

private:
	GnLogger(void);
	~GnLogger(void);

private:
	HMODULE mLogModule;
	bool mLoadLogSystem;
	static GnLogger* msSingletone;
	static GnCriticalSection msCriticalSection;

protected:
	AppendFileFunc mAppendFile;
	AppenOutputDebugFunc mAppenOutputDebug;
	WriteLogFunc mWriteLog;
	WriteFromLoggerLogFunc mWriteFromLoggerLog;
	std::vector<gtstring> mUseLoggerList;
};

#define DEBUGEXT GnText("GNDEBUG")
#define ERRORTEXT GnText("GNERROR")
#define WARINGTEXT GnText("GnWarring")
GNSYSTEM_ENTRY GNFORCEINLINE void GnOutputDebugString(const gtchar* outString);

#if defined(GNDEBUG) || defined(GNLOG)

#define GnLog GnLogger::GetInstance()->WriteLog 
#define GnError GnLogger::GetInstance()->WriteError
#define GnWarring GnLogger::GetInstance()->WriteWarring


#else // defined(GNDEBUG) || defined(GNLOG)

#define GnLog GNNOOP
#define GnError GnLogger::GetInstance()->WriteOutputDebug
#define GnWarring GnLogger::GetInstance()->WriteOutputDebug

#endif // defined(GNDEBUG) || defined(GNLOG)

#define  GnALog GnLogger::GetInstance()->WriteAlways

#include "GnLog.inl"
#endif // GNLOG_H
